﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

class ConvexHull
{



    #region Globals
    Graphics graphics;
    //List<SuperPoint> pointsList = new List<SuperPoint>();
    List<Segment> Segments = new List<Segment>();
    //int pID = 0;
    List<List<SuperPoint>> renderingPoints = new List<List<SuperPoint>>();
    List<List<Segment>> renderingEdges = new List<List<Segment>>();
    List<PointF[]> renderingAreas = new List<PointF[]>();

    List<PointF> edgePoints;
    #endregion


    public ConvexHull(Graphics g)
    {
        this.graphics = g;
    }
    #region Event handlers
   
    #endregion

    #region Functions


    private void renderEdges(List<Segment> edges, List<SuperPoint> pointsList)
    {
        List<PointF> list = new List<PointF>();
        for (int i = 0; i < edges.Count; i++)
        {
            
            if (i == 0)
                list.Add(edges[i].p);

            foreach (Segment s in edges)
            {
                if (s.p == list[list.Count - 1])
                {
                    list.Add(s.q);
                    break;
                }
            }
        }

        Pen p = new Pen(Color.Fuchsia);
      
        foreach (Segment opEdge in edges)
        {
            graphics.DrawLine(p, opEdge.p, opEdge.q);
        }
    

        foreach (SuperPoint sp in pointsList)
        {
           // renderPoint(sp.P.X, sp.P.Y, Color.Lime);
        }

    }
    public void prepareNewConvexHull()
    {
        //pointsList.Clear();
        Segments.Clear();
    }

    public List<PointF> Compute(List<SuperPoint> pointsList)
    {
        List<SuperPoint> ProcessingPoints = new List<SuperPoint>();
        int i = 0;
        int j = 0;
        for (i = 0; i < Segments.Count; )
        {
            //ProcessingPoints will be the points that are not in the current segment
            ProcessingPoints = new List<SuperPoint>(pointsList);

            for (j = 0; j < ProcessingPoints.Count; )
            {

                if (Segments[i].contains(ProcessingPoints[j]))
                {
                    ProcessingPoints.Remove(ProcessingPoints[j]);
                    j = 0;
                    continue;
                }
                j++;

            }

            if (!isEdge(ProcessingPoints, Segments[i]))
            {
                Segments.Remove(Segments[i]);
                i = 0;
                continue;
            }
            else
            { i++; }
        }
        
        //renderEdges(Segments, pointsList);
        edgePoints = new List<PointF>();
        
        foreach (Segment edge in Segments)
        {
            Console.Write("Segment: " + edge.p.ToString() + " and " + edge.q.ToString()+ "\n");
            //if (!edgePoints.Contains(edge.p))
                edgePoints.Add(edge.p);

           // if (!edgePoints.Contains(edge.q))
             //   edgePoints.Add(edge.q);
        }
       // MessageBox.Show(""+edgePoints.Count);
        return edgePoints;
        
    }
    public List<Segment> getSegments()
    {
        return Segments;
    }


    private bool isEdge(List<SuperPoint> processingPoints, Segment edge)
    {
        for (int k = 0; k < processingPoints.Count; k++)
        {
            if (isLeft(edge, processingPoints[k].P))
            {
                return false;
            }
        }
        return true;
    }

    private bool isLeft(Segment segment, PointF r)
    {
        float D = 0;
        float px, py, qx, qy, rx, ry = 0;
        //The determinant
        // | 1 px py |
        // | 1 qx qy |
        // | 1 rx ry |
        //if the determinant result is positive then the point is left of the segment
        px = segment.p.X;
        py = segment.p.Y;
        qx = segment.q.X;
        qy = segment.q.Y;
        rx = r.X;
        ry = r.Y;

        D = ((qx * ry) - (qy * rx)) - (px * (ry - qy)) + (py * (rx - qx));

        if (D <= 0)
            return false;

        return true;
    }

    public void InitOrderdPoints(List<SuperPoint> pointsList)
    {
        //graphics = g;
        Segments.Clear();
        //Initialize all possible segments from the picked points
        for (int i = 0; i < pointsList.Count; i++)
        {
            for (int j = 0; j < pointsList.Count; j++)
            {
                if (i != j)
                {

                    PointF p1 = pointsList[i].P;
                    PointF p2 = pointsList[j].P;
                    Segment op = new Segment(p1, p2);

                    Segments.Add(op);
                }
            }
        }
    }

    #endregion

}
